﻿define([
    "dojo/_base/declare", "dojo/_base/connect", "dojo/_base/array",
    "dojo/dom-construct", "dojo/dom-style", "dojo/number",
    "esri/lang", "esri/domUtils",
    "esri/SpatialReference", "esri/geometry/Point", "esri/layers/layer"
  ], function (
    declare, connect, arrayUtils,
    domConstruct, domStyle, number,
    esriLang, domUtils,
    SpatialReference, Point, Layer
  ) {
      var RL = declare([Layer], {
          // Doc: http://docs.dojocampus.org/dojo/declare#chaining
          "-chains-": {
              constructor: "manual"
          },

          constructor: function (data, options) {
              // Manually call superclass constructor with required arguments
              this.inherited(arguments, ["http://some.server.com/path", options]);

              this.data = data;

              this.loaded = true;
              this.onLoad(this);
          },

          /********************
          * Public Properties
          *
          * data
          *
          ********************/

          /**********************
          * Internal Properties
          *
          * _map
          * _element
          * _context
          * _mapWidth
          * _mapHeight
          * _connects
          *
          **********************/

          /******************************
          * esri.layers.Layer Interface
          ******************************/

          _setMap: function (map, container) {
              this._map = map;

              var element = this._element = domConstruct.create("canvas", {
                  id: "canvas",
                  width: map.width + "px",
                  height: map.height + "px",
                  style: "position: absolute; left: 0px; top: 0px;"
              }, container);

              if (esriLang.isDefined(this.opacity)) {
                  domStyle.set(element, "opacity", this.opacity);
              }

              this._context = element.getContext("2d");
              if (!this._context) {
                  console.error("This browser does not support <canvas> elements.");
              }

              this._mapWidth = map.width;
              this._mapHeight = map.height;

              // Event connections
              this._connects = [];
              this._connects.push(connect.connect(map, "onPan", this, this._panHandler));
              this._connects.push(connect.connect(map, "onExtentChange", this, this._extentChangeHandler));
              this._connects.push(connect.connect(map, "onZoomStart", this, this.clear));
              this._connects.push(connect.connect(this, "onVisibilityChange", this, this._visibilityChangeHandler));

              return element;
          },

          _unsetMap: function (map, container) {
              arrayUtils.forEach(this._connects, connect.disconnect, this);
              if (this._element) {
                  container.removeChild(this._element);
              }
              this._map = this._element = this._context = this.data = this._connects = null;
          },

          /*****************
          * Public Methods
          *****************/

          refresh: function () {
              if (!this._canDraw()) {
                  return;
              }
          },

          clear: function () {
              if (!this._canDraw()) {
                  return;
              }

              this._context.clearRect(0, 0, this._mapWidth, this._mapHeight);
          },

          /*******************
          * Internal Methods
          *******************/

          _canDraw: function () {
              return (this._map && this._element && this._context) ? true : false;
          },

          _panHandler: function (extent, delta) {
              domStyle.set(this._element, { left: delta.x + "px", top: delta.y + "px" });
          },

          _extentChangeHandler: function (extent, delta, levelChange, lod) {
              if (!levelChange) {
                  domStyle.set(this._element, { left: "0px", top: "0px" });
                  this.clear();
              }
          },

          /****************
          * Miscellaneous
          ****************/

          _visibilityChangeHandler: function (visible) {
              if (visible) {
                  domUtils.show(this._element);
              }
              else {
                  domUtils.hide(this._element);
              }
          },

          hideLayer: function () {
              this.visible = false;
              this._elementVisible = false;
              this._canvas.style.display = 'none';
          },
          showLayer: function () {
              this.visible = true;
              this._elementVisible = true;
              this._canvas.style.display = 'block';
          },
          setScale: function (map, _element) {
              var scale = map.getScale();

              if (this.options && this.options.minScale && this.options.maxScale) {
                  if (scale > this.options.minScale || scale < this.options.maxScale) {
                      _element.style.display = 'none';
                      this._elementVisible = false;
                  } else {
                      _element.style.display = 'block';
                      this._elementVisible = true;
                  }
                  ;
              } else if (this.options && this.options.minScale > 0) {
                  if (scale > this.options.minScale) {
                      _element.style.display = 'none';
                      this._elementVisible = false;
                  } else {
                      _element.style.display = 'block';
                      this._elementVisible = true;
                  }
                  ;
              } else if (this.options && this.options.maxScale > 0) {
                  if (scale < this.options.maxScale) {
                      _element.style.display = 'none';
                      this._elementVisible = false;
                  } else {
                      _element.style.display = 'block';
                      this._elementVisible = true;
                  }
                  ;
              } else {
                  _element.style.display = 'block';
                  this._elementVisible = true;
              }
              ;
          }

      });

      return RL;
  });